﻿using Lazy.Captcha.Core;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using RabbitManage.EntityFrameworkCore;
using SMARTHOTEL.Permissiones;
using SMARTHOTEL.Roles;
using SMARTHOTEL.User;
using SMARTHOTEL.UserRoleDto;
using SMARTHOTEL.VerificationCode;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt; // 关键命名空间
using System.IO;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;


namespace SMARTHOTEL.Users
{

    /// <summary>
    /// 用户角色权限接口
    /// </summary>
    [Route("api/v2/users")]
    [ApiExplorerSettings(GroupName = "v2")]
    public class UserService : ApplicationService, IServiceUsers
    {
        private readonly IConfiguration _configuration;
  
        private readonly ICaptcha _captcha;
       
        private readonly IRepository<User> Userrepository;
        private readonly IRepository<Role> RoleRepository;
        private readonly IRepository<RolePermissions> RolePermissionsRepository;
        private readonly IRepository<UserRole> UserRoleRepository;
        private readonly IRepository<Permissions> PermissionsRepository;



       

     

        public UserService( ICaptcha captcha, IConfiguration configuration, IRepository<User> userrepository, IRepository<Role> roleRepository, IRepository<RolePermissions> rolePermissionsRepository, IRepository<UserRole> userRoleRepository, IRepository<Permissions> permissionsRepository)

        {
            
            _captcha = captcha;
            _configuration = configuration;
            Userrepository = userrepository;
            RoleRepository = roleRepository;
            RolePermissionsRepository = rolePermissionsRepository;
            UserRoleRepository = userRoleRepository;
            PermissionsRepository = permissionsRepository;
        }








        /// <summary>
        /// 注册用户
        /// </summary>
        /// <param name="user">实体</param>
        /// <returns>返回任务</returns>
        [HttpPost("Users")]
        public async Task<APIResult> AddUser(UserDto user)
        {
            // 判断用户名是否存在
            var users = await Userrepository.FirstOrDefaultAsync(t => t.UserName == user.UserName);
            if (users == null)
            {
                //添加用户表
                var list = ObjectMapper.Map<UserDto, User>(user);
                await Userrepository.InsertAsync(list);
                return APIResult.OK(data: list);
            }
            else
            {
                return APIResult.Fail("用户名已存在");
            }
        }
        /// <summary>
        /// 添加用户角色
        /// </summary>
        /// <param name="userRoledto"></param>
        /// <returns></returns>
        [HttpPost("UserRole")]
        public async Task<APIResult> AddUserRole(UserRoledto userRoledto)
        {
            //添加用户角色表
            var userrole = new UserRole()
            {
                UserId = userRoledto.UserId,
                RoleId = userRoledto.RoleId,
            };
            await UserRoleRepository.InsertAsync(userrole);
            return APIResult.OK(data: userRoledto);
        }
        /// <summary>
        /// 添加角色
        /// </summary>
        /// <param name="roles"></param>
        /// <returns></returns>
        [HttpPost("Roles")]
        public async Task<APIResult> AddRole(RoleDto roles)
        {
            var list = await RoleRepository.FirstOrDefaultAsync(t => t.RoleName == roles.RoleName);
            if (list != null)
            {
                return APIResult.Fail("角色已存在");
            }
            var role = new Role()
            {
                RoleName = roles.RoleName
            };
            // 添加角色表
            await RoleRepository.InsertAsync(role);
            return APIResult.OK(data: roles);
        }
        /// <summary>
        /// 添加权限
        /// </summary>
        /// <param name="permissionsDto"></param>
        /// <returns></returns>
        [HttpPost("Permissions")]
        public async Task<APIResult> AddPermissions(PermissionsDto permissionsDto)
        {
            var list = await PermissionsRepository.FirstOrDefaultAsync(t => t.PermissionName == permissionsDto.PermissionsName);
            if (list != null)
            {
                return APIResult.Fail("权限已存在");
            }
            var permissions = new Permissions()
            {
                PermissionName = permissionsDto.PermissionsName,
                ParentId = permissionsDto.ParentId
            };
            // 添加权限表
            await PermissionsRepository.InsertAsync(permissions);

            return APIResult.OK(data: permissions);
        }
        /// <summary>
        /// 获取角色
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetRole")]
        public async Task<APIResult> GetRole()
        {
            var list = await RoleRepository.GetListAsync();
            return APIResult.OK(data: list);
        }
        /// <summary>
        /// 获取权限
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetPermissions")]
        public async Task<APIResult> GetPermissions()
        {
            var list = await PermissionsRepository.GetListAsync();
            return APIResult.OK(data: list);
        }
        /// <summary>
        /// 角色权限
        /// </summary>
        /// <param name="rolePermissionesDto"></param>
        /// <returns></returns>
        [HttpPost("RolePermissions")]
        public async Task<APIResult> AddRolePermissions(RolePermissionesDto rolePermissionesDto)
        {
            // 循环添加角色权限表(每一个角色对应多个权限)
            foreach (var item in rolePermissionesDto.PermissionId)
            {
                // 添加角色权限表
                var rolePermissions = new RolePermissions()
                {
                    RoleId = rolePermissionesDto.RoleId,
                    PermissionId = item
                };
                await RolePermissionsRepository.InsertAsync(rolePermissions);
            }
            return APIResult.OK(data: rolePermissionesDto);
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <returns>返回任务</returns>
        [HttpPost("api/v1/auth/login")]
        public async Task<RoomTypes.ResultDto<LoginDto>> Login([FromForm] IntroducedLoginDto introduced)
        {

            var pwd = Md5(introduced.Password);
            var user = await Userrepository.FirstOrDefaultAsync(t => t.UserName == introduced.Username);
            var token = CreateTokenString(user);
            if (user == null)
            {
                return new RoomTypes.ResultDto<LoginDto> { Code = RoomTypes.StatusCode.Faield, Message = "用户不存在" };
            }
            if (user.UserIsLock)
            {
                return new RoomTypes.ResultDto<LoginDto> { Code = RoomTypes.StatusCode.Faield, Message = "用户已被锁定" };
            }
            if (user.UserPwd != pwd)
            {
                user.UserErrorCount++;
                await Userrepository.UpdateAsync(user);
                if (user.UserErrorCount >= 5)
                {
                    user.UserIsLock = true;
                    await Userrepository.UpdateAsync(user);
                    return new RoomTypes.ResultDto<LoginDto> { Code = RoomTypes.StatusCode.Faield, Message = "用户名和密码不匹配,错误次数已达5次,该账号被锁定" };
                }
                return new RoomTypes.ResultDto<LoginDto> { Code = RoomTypes.StatusCode.Faield, Message = $"用户名和密码错误，已输错{user.UserErrorCount}次,剩余{5 - user.UserErrorCount}次" };
            }
            if (user.UserErrorCount > 0)
            {
                user.UserErrorCount = 0;
                await Userrepository.UpdateAsync(user);
            }
            return new RoomTypes.ResultDto<LoginDto>
            {
                Code = RoomTypes.StatusCode.Success,
                Message = "登录成功",
                Data = new LoginDto
                {
                    tokenType = "Bearer",
                    AccessToken = token,
                    expiresIn = 7200,
                    refreshToken = token,
                }
            };
        }   



       

        /// <summary>
        /// 验证码
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("/api/v1/auth/captcha")]
        public Task<RoomTypes.ResultDto<VerificationCodeDto>> Captcha(string id)
        {
            var info = _captcha.Generate(id);
            // 有多处验证码且过期时间不一样，可传第二个参数覆盖默认配置。
            //var info = _captcha.Generate(id,120);
            var stream = new MemoryStream(info.Bytes);

            var base64String = $"data:image/png;base64,{Convert.ToBase64String(stream.ToArray())}";

            var verificationCodeDto = new VerificationCodeDto
            {
                captchaKey = id,
                captchaBase64 = base64String

            };

            RoomTypes.ResultDto<VerificationCodeDto> result = new RoomTypes.ResultDto<VerificationCodeDto> 
            {
                
                Code = RoomTypes.StatusCode.Success,
                Message = "成功",
                
                
                Data = verificationCodeDto};

            return Task.FromResult(result);
        }
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string Md5(string str)
        {
            var md5 = MD5.Create();
            Byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
            return BitConverter.ToString(bytes).Replace("-", "").ToUpper();
        }
       




        ///// <summary>
        ///// 生成JWT Token
        ///// </summary>
        ///// <param name="user">用户信息</param>
        ///// <returns>JWT Token字符串</returns>
        //private string GenerateToken(User user)
        //{
        //    // 声明部分：添加用户相关Claims
        //    var claims = new List<Claim>
        //        {
        //            new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
        //            new Claim(JwtRegisteredClaimNames.FamilyName, user.UserName),
        //        };


        //    // 可根据需要添加更多声明，如角色等
        //    // new Claim(JwtClaimTypes.Role, user.Role)


        //    // 从配置获取JWT参数（建议使用IOptions模式注入）
        //    var securityKey = _configuration["JwtConfig:Bearer:SecurityKey"];
        //    if (string.IsNullOrEmpty(securityKey) || securityKey.Length < 32)
        //    {
        //        throw new ArgumentException("无效的JWT安全密钥，长度至少32字符。");
        //    }

        //    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey));

        //    // 使用HmacSha256算法签名
        //    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        //    // 从配置获取过期时间（建议默认值或配置校验）
        //    var expiresMinutes = Convert.ToInt32(_configuration["JwtConfig:Bearer:ExpiresMinutes"] ?? "30");
        //    var expires = DateTime.UtcNow.AddMinutes(expiresMinutes);

        //    // 构建Token
        //    var token = new JwtSecurityToken(
        //        issuer: _configuration["JwtConfig:Bearer:Issuer"],
        //        audience: _configuration["JwtConfig:Bearer:Audience"],
        //        claims: claims,
        //        notBefore: DateTime.UtcNow,
        //        expires: expires,
        //        signingCredentials: creds
        //    );

        //    // 生成Token字符串
        //    return new JwtSecurityTokenHandler().WriteToken(token);
        //}

 
        /// <summary>
        /// 获取用户列表(RBAC)
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetUser")]
        public async Task<APIResult> GetUser()
        {
            var list = (from a in await Userrepository.GetQueryableAsync()
                        join b in await UserRoleRepository.GetQueryableAsync() on a.Id equals b.UserId
                        join c in await RoleRepository.GetQueryableAsync() on b.RoleId equals c.Id
                        join d in await RolePermissionsRepository.GetQueryableAsync() on c.Id equals d.RoleId
                        join e in await PermissionsRepository.GetQueryableAsync() on d.PermissionId equals e.Id
                        select new UserDto()
                        {
                            UserId = a.Id,
                            UserName = a.UserName,
                            UserPwd = a.UserPwd,
                            UserNickName = a.UserNickName,
                            UserErrorCount = a.UserErrorCount,
                            UserIsLock = a.UserIsLock,
                            RoleId = b.Id,
                            RoleName= c.RoleName,
                            RolePermissionsId=d.Id,
                            PermissionId = e.Id,
                            PermissionName = e.PermissionName,
                            ParentId = e.ParentId
                        }).ToList();
            return APIResult.OK(data:list);
        }



        /// <summary>
        /// 生成 JWT Token（令牌）
        /// </summary>
        /// <returns></returns>
        private string CreateTokenString(User user)
        {
            IList<Claim> claims = new List<Claim> {
                                new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
                                new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName),

                            };

            //私钥
            var secretByte = Encoding.UTF8.GetBytes("kdsfldsflkdslkflkdsflkdslfdslkflk");
            // 非对称加密
            var signingKey = new SymmetricSecurityKey(secretByte);
            // 使用256 生成数字签名
            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
            // 生成Token
            var token = new JwtSecurityToken(
                issuer: "BeiJingBW",
                audience: "BeiJingBW",
                 claims: claims,
                  notBefore: DateTime.UtcNow,
                expires: DateTime.Now.AddDays(1), // 一天后过期
                signingCredentials: signingCredentials
            );
            // 生成token 字符串
            var strToken = new JwtSecurityTokenHandler().WriteToken(token);
            return strToken;
        }
    };
}




